#pragma once

#include <vex/core/contract/handle.h>
#include <vex/functional/contract/delegate.h>
#include <vex/functional/contract/signal_connection.h>

namespace vex { namespace functional { namespace contract {

    /// <summary>
    /// Abstraction for the ability to add and remove an delegate<TSignature>
    /// to and from an invocation list of some multicast signal but not to invoke it. 
    /// Use this contract in client code contracts to expose an endpoint of multicast service.
    /// </summary>
    ///
    /// The signatures of the connected types must be identical. Implementations
    /// are required to provide full thread safety guarantees for adding and removal
    /// of delegates.
    template<class TSignature> 
    struct VEX_ABSTRACT signal : virtual public core::contract::handle
    {
        typedef delegate<TSignature> delegate_type;

        /// <summary>
        /// Connect the passed delegate to signal. Returns a connection object, 
        /// if <param>p_connection_required</param> equals connection_required::yes. The connection object
        /// can be used to diconnect from this multicast service without the explicit knowledge
        /// about the service instance. Implementations are required to provide full thread safety gurantee.
        /// Shall return a valid connection object if successfully connected, nullptr otherwise.
        /// </summary>
        virtual signal_connection* connect(
            delegate<TSignature>* p_delegate,
            connection_required::domain p_connection_required = connection_required::no) = 0;

        VEX_PROTECT_CONTRACT(signal);
    };
}}}